#ifndef __IM_MEMORY_CHUNK_H__
#define __IM_MEMORY_CHUNK_H__

#include <stdio.h>
#include <im_base_types.h>
#include <im_object.h>
#include <im_io_channel.h>
/**
 * @defgroup IMMemoryChunk
 * @ingroup PrivateIMBusIME
 * @{
 */

/** @struct IMMemoryChunk
 *  @brief A class to manage a large chunk of memory.
 *
 * A chunk can be allocated in memory as well as loaded
 * from a file by mmapping.
 *
 * A chunk can also be a sub portion of another chunk.
 *
 * A chunk can be saved into a file.
 *
 * Copy on write is supported.
 */

IM_BEGIN_DECLS

#define IM_MEMORY_CHUNK(p)           (IM_TYPE_INSTANCE_CHECK_CAST((p),IM_TYPE_MEMORY_CHUNK,IMMemoryChunk))
#define IM_CONST_MEMORY_CHUNK(p)     (IM_TYPE_INSTANCE_CHECK_CAST_CONST((p),IM_TYPE_MEMORY_CHUNK,IMMemoryChunk))
#define IM_MEMORY_CHUNK_CLASS(c)     (IM_TYPE_CLASS_CHECK_CAST((c),IM_TYPE_MEMORY_CHUNK,IMMemoryChunkClass))
#define IM_IS_MEMORY_CHUNK(p)        (IM_TYPE_INSTANCE_CHECK_TYPE((p),IM_TYPE_MEMORY_CHUNK))
#define IM_IS_MEMORY_CHUNK_CLASS(c)  (IM_TYPE_CLASS_CHECK_TYPE((c),IM_TYPE_MEMORY_CHUNK))
#define IM_MEMORY_CHUNK_GET_CLASS(p) (IM_TYPE_INSTANCE_GET_CLASS_CAST((p),IM_TYPE_MEMORY_CHUNK,IMMemoryChunkClass))

typedef struct _IMMemoryChunk        IMMemoryChunk;
typedef struct _IMMemoryChunkClass   IMMemoryChunkClass;


/**
 * @brief Create a new memory chunk with given preallocated size.
 */
IMMemoryChunk*  im_memory_chunk_new             (IMSize                  size);

/**
 * @brief Create a new memory chunk copying the content from a given
 *        buffer.
 */
IMMemoryChunk*  im_memory_chunk_new_from_buffer (IMConstPointer          buffer,
                                                 IMSize                  size);

/**
 * @brief Clear the content of a memory chunk.
 */
void            im_memory_chunk_clear           (IMMemoryChunk          *chunk);

/**
 * @brief Get a sub portion of a memory chunk.
 *
 * @param chunk The original chunk.
 * @param start Start position of sub chunk in the original chunk.
 * @param size  Size of sub chunk.
 * @param copy  Whether actually copy the content or just share the content
 *              with original chunk.
 */
IMMemoryChunk*  im_memory_chunk_get_sub_chunk   (const IMMemoryChunk    *chunk,
                                                 IMSize                  start,
                                                 IMSize                  size,
                                                 IMBool                  copy);

/**
 * @brief Append another memory chunk to the end of a memory chunk.
 */
IMMemoryChunk*  im_memory_chunk_append          (IMMemoryChunk          *chunk,
                                                 const IMMemoryChunk    *append);

/**
 * @brief Prepend another memory chunk to the begining of a memory chunk.
 */
IMMemoryChunk*  im_memory_chunk_prepend         (IMMemoryChunk          *chunk,
                                                 const IMMemoryChunk    *prepend);

/**
 * @brief Append a byte buffer to the end of a memory chunk.
 */
IMMemoryChunk*  im_memory_chunk_append_buffer   (IMMemoryChunk          *chunk,
                                                 IMConstPointer          buffer,
                                                 IMSize                  size);

/**
 * @brief Prepend a byte buffer to the begining of a memory chunk.
 */
IMMemoryChunk*  im_memory_chunk_prepend_buffer  (IMMemoryChunk          *chunk,
                                                 IMConstPointer          buffer,
                                                 IMSize                  size);

/**
 * @brief Take the ownership of a preallocated byte buffer.
 *
 * The memory chunk will just use the given buffer and will release it
 * when destroying.
 *
 * The buffer must be allocated by im_malloc(), so that it can be
 * freed or resized.
 */
void            im_memory_chunk_take_buffer     (IMMemoryChunk          *chunk,
                                                 IMPointer               buffer,
                                                 IMSize                  size);

/**
 * @brief Get buffer pointer of a memory chunk for read and write purpose.
 *
 * If the given chunk is sharing content with another chunk, then
 * the content will be copied before returning the pointer.
 */
IMPointer       im_memory_chunk_get_ptr         (IMMemoryChunk          *chunk);

/**
 * @brief Get const buffer pointer of a memory chunk for readonly purpose.
 *
 * The content won't be copied even it's shared with another memory chunk.
 */
IMConstPointer  im_memory_chunk_get_const_ptr   (const IMMemoryChunk    *chunk);

/**
 * @brief Get content size of a memory chunk.
 */
IMSize          im_memory_chunk_get_size        (const IMMemoryChunk    *chunk);

/**
 * @brief Get checksum of a memory chunk.
 */
IMUInt32        im_memory_chunk_get_checksum    (const IMMemoryChunk    *chunk);

/**
 * @brief Ensure a memory chunk having a least given space.
 */
IMBool          im_memory_chunk_ensure_size     (IMMemoryChunk          *chunk,
                                                 IMSize                  size);

/**
 * @brief Reduce the size of a memory chunk. The content will be truncated.
 */
IMBool          im_memory_chunk_reduce_size     (IMMemoryChunk          *chunk,
                                                 IMSize                  size);

/**
 * @brief Load content from a file.
 *
 * @param fp handler of an opened file.
 * @param nbytes load at most nbytes bytes, -1 means as many as possible.
 * @param timeout the timeout to load memory chunk from the io channel.
 *                in milliseconds. -1 mean wait forever until enough data
 *                are read. Be careful that if both nbytes and timeout
 *                equal to -1, it'll go into an endless loop on an io channel
 *                with unknown size of data in it. When return the remained
 *                timeout will be stored in it.
 */
IMBool          im_memory_chunk_load            (IMMemoryChunk          *chunk,
                                                 IMIOChannel            *iochannel,
                                                 IMSize                  nbytes,
                                                 IMInt                  *timeout,
                                                 IMIOError              *error);

/**
 * @brief Save content to a file.
 *
 * @param fp handler of an opened file.
 * @param nbytes save at most nbytes bytes, -1 means as many as possible.
 * @param timeout the timeout to save memory chunk to the io channel.
 *                in milliseconds. -1 mean wait forever until all data
 *                are written into the io channel.
 */
IMBool          im_memory_chunk_save            (IMMemoryChunk          *chunk,
                                                 IMIOChannel            *iochannel,
                                                 IMSize                  nbytes,
                                                 IMInt                  *timeout,
                                                 IMIOError              *error);
IM_END_DECLS
/** @} */

#endif
/*
vi:ts=4:nowrap:ai:expandtab
*/
